
from ctypes import *

VCI_USBCAN2 = 4
STATUS_OK = 1
ubyte_array = c_ubyte*8
ubyte_3array = c_ubyte*3
reserved = ubyte_3array(0,0,0)
class can_message:

    class VCI_INIT_CONFIG(Structure):  
        _fields_ = [("AccCode", c_uint), # 验收码。对经过屏蔽码过滤为“有关位”进行匹配，全部匹配成功后，此帧可以被接收。
                    ("AccMask", c_uint), # 屏蔽码。对接收的CAN帧ID进行过滤，对应位为0的是“有关位”，对应位为1的是“无关位”。
                    ("Reserved", c_uint), # 保留。
                    ("Filter", c_ubyte), # 滤波方式，0/1 接收所有类型 2 只接收标准帧 3 只接收扩展帧
                    ("Timing0", c_ubyte), # 波特率定时器 0（BTR0）常见波特率参照波特表
                    ("Timing1", c_ubyte), # 波特率定时器 1（BTR1）。
                    ("Mode", c_ubyte) # 模式。=0表示正常模式（相当于正常节点），=1表示只听模式（只接收，不影响总线） =2表示自发自收模式（环回模式）
                    ]  

    class VCI_CAN_OBJ(Structure):  
        _fields_ = [("ID", c_uint), # 帧ID，32位变量，左对齐
                    ("TimeStamp", c_uint), # 设备接收到某一帧的时间标识。时间标示从CAN卡上电开始计时，计时单位为0.1ms。
                    ("TimeFlag", c_ubyte), # 是否使用时间标识，为1时TimeStamp有效，TimeFlag和TimeStamp只在此帧为接收帧时有意乂
                    ("SendType", c_ubyte), # 发送帧类型。=0时为正常发送（发送失败会自动重发，重发时间为4秒，4秒内没有发出则取消）；=1时为单次发送（只发送一次，发送失败不会自动重发，总线只产生一帧数据）；其它值无效。
                    ("RemoteFlag", c_ubyte), # 是否是远程帧。=0时为为数据帧，=1时为远程帧（数据段空）。
                    ("ExternFlag", c_ubyte), # 是否是扩展帧。=0时为标准帧（11位ID），=1时为扩展帧（29位ID）
                    ("DataLen", c_ubyte), # 数据长度 DLC (<=8)，即CAN帧Data有几个字节。约束了后面Data[8]中的有效字节
                    ("Data", c_ubyte*8), # CAN帧的数据。由于CAN规定了最大是8个字节，所以这里预留了8个字节的空间，
                    ("Reserved", c_ubyte*3) # 系统保留。
                    ] 
    
    def __init__(self):
        self.CanDLLName = './ControlCAN.dll' #把DLL放到对应的目录下
        self.canDLL = windll.LoadLibrary('./ControlCAN.dll')
        print(self.CanDLLName)
        ret = self.canDLL.VCI_OpenDevice(VCI_USBCAN2, 0, 0)
        if ret == STATUS_OK:
            print('调用 VCI_OpenDevice成功\r\n')
        if ret != STATUS_OK:
            print('调用 VCI_OpenDevice出错\r\n')
        vci_initconfig = self.VCI_INIT_CONFIG(0x80000008, 0xFFFFFFFF, 0, 0, 0x00, 0x1C, 0)#波特率500k，正常模式
        ret = self.canDLL.VCI_InitCAN(VCI_USBCAN2, 0, 0, byref(vci_initconfig))
        if ret == STATUS_OK:
            print('调用 VCI_InitCAN1成功\r\n')
        if ret != STATUS_OK:
            print('调用 VCI_InitCAN1出错\r\n')
        
        ret = self.canDLL.VCI_StartCAN(VCI_USBCAN2, 0, 0)
        if ret == STATUS_OK:
            print('调用 VCI_StartCAN1成功\r\n')
        if ret != STATUS_OK:
            print('调用 VCI_StartCAN1出错\r\n')
        
    def sendTurnLeft(self):
        turn_left=self.VCI_CAN_OBJ(0x18FFC825, 0, 0, 1, 0, 0, 2, ubyte_array(0,1), reserved)
        ret = self.canDLL.VCI_Transmit(VCI_USBCAN2, 0, 0, byref(turn_left), 1)
        if ret == STATUS_OK:
            print("sendTurnLeft")
        if ret != STATUS_OK:
            print("sendTurnLeft Error")
    
    def sendTurnRight(self):
        turn_right=self.VCI_CAN_OBJ(0x18FFC825, 0, 0, 1, 0, 0, 2, ubyte_array(0,4), reserved)
        ret = self.canDLL.VCI_Transmit(VCI_USBCAN2, 0, 0, byref(turn_right), 1)
        if ret == STATUS_OK:
            print("sendTurnRight")
        if ret != STATUS_OK:
            print("sendTurnRight Error")

    def sendStraight(self):
        turn_right=self.VCI_CAN_OBJ(0x18FFC825, 0, 0, 1, 0, 0, 2, ubyte_array(0,0), reserved)
        ret = self.canDLL.VCI_Transmit(VCI_USBCAN2, 0, 0, byref(turn_right), 1)
        if ret == STATUS_OK:
            print("sendTurnRight")
        if ret != STATUS_OK:
            print("sendTurnRight Error")

    def sendSpeed(self,speed):
        speeds=self.VCI_CAN_OBJ(0x0CFE6CEE, 0, 0, 1, 0, 0, 8, ubyte_array(0,0,0,0,0,0,speed//128,speed%128), reserved)
        ret = self.canDLL.VCI_Transmit(VCI_USBCAN2, 0, 0, byref(speeds), 1)
        if ret == STATUS_OK:
            print("sendSpeed = "+str(speed))
        if ret != STATUS_OK:
            print("sendSpeed Error")
    
    def sendGears(self,gear):
        gears=self.VCI_CAN_OBJ(0x18F00503, 0, 0, 1, 0, 0, 4, ubyte_array(0,0,0,gear), reserved)
        ret = self.canDLL.VCI_Transmit(VCI_USBCAN2, 0, 0, byref(gears), 1)
        if ret == STATUS_OK:
            print("sendGears = "+str(gear))
        if ret != STATUS_OK:
            print("sendGears Error")
    
    def sendBrake(self,brake):
        brakes=self.VCI_CAN_OBJ(0x18F0010B, 0, 0, 1, 0, 0, 2, ubyte_array(0,brake), reserved)
        ret = self.canDLL.VCI_Transmit(VCI_USBCAN2, 0, 0, byref(brakes), 1)
        if ret == STATUS_OK:
            print("sendBrake = "+str(brake))
        if ret != STATUS_OK:
            print("sendBrake Error")

    
